<template>
  <view class="popover" :class="[`popover--${placement}`]" :style="[getStyle]">
    <view class="popover__reference" @click.stop="handleClick">
      <slot name="reference" />
    </view>
    <view v-show="show" class="popover__content">
      <view :style="[getOffsetStyle]" class="popover__content__offset">
        <view v-if="$slots.default" class="popover__content__item">
          <slot />
        </view>
        <template v-else-if="list.length">
          <view
            v-for="(item, itemIndex) in list"
            :key="itemIndex"
            class="popover__content__item"
            :class="[{ disabled: item.disabled }]"
            @click="handleChoose(item, itemIndex)"
          >
            <view class="popover__content__item__text">
              <m-icon
                v-if="item.icon"
                :name="item.icon"
                size="32"
                color="inherit"
                class="popover__content__item__icon"
              />
              {{ item[label] }}
            </view>
          </view>
        </template>
      </view>
    </view>
    <view v-show="show" class="popover__arrow" />
  </view>
</template>

<script lang="ts">
import { computed, defineComponent, ref, watch, onMounted, onUnmounted } from '@vue/composition-api'
import { useRouter } from '@/hooks'

export default defineComponent({
  props: {
    placement: {
      type: String,
      default: 'bottom-start',
    },
    width: {
      type: Number,
      default: 200,
    },
    offset: {
      type: Array,
      default: () => [0, 0],
    },
    list: {
      type: Array,
      default: () => [],
    },
    theme: {
      type: String,
      default: 'light',
    },
    label: {
      type: String,
      default: 'name',
    },
  },
  emits: ['change', 'open', 'close'],
  setup(props, { emit }) {
    const router: any = useRouter()
    const show = ref(false)
    const getOffsetStyle = computed(() => {
      const [marginLeft, marginRight] = props.offset

      return {
        width: props.width + 'rpx',
        marginLeft: (marginLeft || 0) + 'rpx',
        marginRight: (marginRight || 0) + 'rpx',
      }
    })
    onMounted(() => {
      uni.$on('closePopover', () => {
        show.value = false
      })
    })
    onUnmounted(() => {
      uni.$off('closePopover')
    })
    const handleClick = () => {
      if (show.value === false) {
        uni.$emit('closePopover')
      }
      show.value = !show.value
    }
    const getStyle = computed(() => {
      if (props.theme === 'light') {
        return { '--popover-color': '#262626', '--popover-bg': 'rgba(255, 255, 255, 0.95)' }
      }

      return { '--popover-color': '#fff', '--popover-bg': 'rgba(0, 0, 0, 0.95)' }
    })
    const handleChoose = (item, itemIndex) => {
      if (item.disabled) {
        return
      }
      emit('choose', item, itemIndex)
      show.value = false
      if (item.to) {
        const routerName = item.to && (item.to.name as string)
        if (['Index', 'Category', 'Community', 'Example', 'Mine', 'Cart'].includes(routerName)) {
          router.pushTab(item.to)
        } else {
          router[item.replace ? 'replace' : 'push'](item.to)
        }

        return
      }
    }
    watch(
      () => show.value,
      (newVal) => {
        if (newVal) {
          emit('open')
        } else {
          emit('close')
        }
      }
    )

    return {
      getStyle,
      show,
      getOffsetStyle,
      handleClick,
      handleChoose,
    }
  },
})
</script>
<style lang="scss" scoped>
.popover {
  display: inline-block;
  position: relative;
  &__reference {
    z-index: 9;
  }
  &__content {
    z-index: 11;
    position: absolute;
    &__offset {
      box-shadow: 0 2rpx 12rpx 0 rgba(0, 0, 0, 0.1);
      background: var(--popover-bg);
      color: var(--popover-color);
      border-radius: 8rpx;
      z-index: 11;
    }
    &__item {
      padding: 20rpx 16rpx;
      border-radius: 10rpx;
      min-height: 48rpx;
      position: relative;
      &__icon {
        margin-right: 16rpx;
      }
      &__text {
        display: flex;
        justify-content: center;
        align-items: center;
      }
      &::after {
        position: absolute;
        box-sizing: border-box;
        content: ' ';
        pointer-events: none;
        right: 0;
        bottom: 0;
        left: 0;
        transform: scaleY(0.5);
        border-bottom: 2rpx solid $--line-c;
      }
      &:last-child {
        &::after {
          border: 0 !important;
        }
      }
      &.disabled {
        color: #9a9b9d;
        cursor: not-allowed;
      }
    }
  }
  &__arrow {
    position: absolute;
    z-index: 11;
    &::before {
      content: '';
      position: absolute;
      width: 0;
      height: 0;
      filter: drop-shadow(0 2rpx 12rpx rgba(0, 0, 0, 0.03));
    }
  }

  // & + .popover {
  //   margin-left: 32rpx;
  // }

  &--bottom,
  &--bottom-start,
  &--bottom-end {
    .popover__content {
      top: 100%;
      margin-top: 24rpx;
    }
    .popover__arrow {
      left: 50%;
      transform: translateX(-50%);
      top: 100%;
      margin-top: 24rpx;
      &::before {
        top: -10rpx;
        left: 50%;
        transform: translateX(-50%);
        border-right: 10rpx solid transparent;
        border-left: 10rpx solid transparent;
        border-bottom: 10rpx solid var(--popover-bg);
      }
    }
  }

  &--top,
  &--top-start,
  &--top-end {
    .popover__content {
      bottom: 100%;
      margin-bottom: 24rpx;
    }
    .popover__arrow {
      left: 50%;
      transform: translateX(-50%);
      bottom: 100%;
      margin-bottom: 24rpx;
      &::before {
        bottom: -10rpx;
        left: 50%;
        transform: translateX(-50%);
        border-right: 10rpx solid transparent;
        border-left: 10rpx solid transparent;
        border-top: 10rpx solid var(--popover-bg);
      }
    }
  }
  &--top-start,
  &--bottom-start {
    .popover__content {
      left: 0;
    }
  }
  &--top,
  &--bottom {
    .popover__content {
      left: 50%;
      transform: translateX(-50%);
    }
  }
  &--top-end,
  &--bottom-end {
    .popover__content {
      right: 0;
    }
  }

  &--right,
  &--right-start,
  &--right-end {
    .popover__content {
      left: 100%;
      margin-left: 24rpx;
    }
    .popover__arrow {
      top: 50%;
      transform: translateY(-50%);
      left: 100%;
      margin-left: 24rpx;
      &::before {
        left: -10rpx;
        top: 50%;
        transform: translateY(-50%);
        border-top: 10rpx solid transparent;
        border-bottom: 10rpx solid transparent;
        border-right: 10rpx solid var(--popover-bg);
      }
    }
  }

  &--left,
  &--left-start,
  &--left-end {
    .popover__content {
      right: 100%;
      margin-right: 24rpx;
    }
    .popover__arrow {
      top: 50%;
      transform: translateY(-50%);
      right: 100%;
      margin-right: 24rpx;
      &::before {
        right: -10rpx;
        top: 50%;
        transform: translateY(-50%);
        border-top: 10rpx solid transparent;
        border-bottom: 10rpx solid transparent;
        border-left: 10rpx solid var(--popover-bg);
      }
    }
  }

  &--right-start,
  &--left-start {
    .popover__content {
      top: 0;
    }
  }
  &--right,
  &--left {
    .popover__content {
      top: 50%;
      transform: translateY(-50%);
    }
  }
  &--right-end,
  &--left-end {
    .popover__content {
      bottom: 0;
    }
  }
}
</style>
